﻿using LibNiconico.NiconicoApi.Lives.Broadcast;
using NicoView.Model.Share.MediaEncoders;
using NicoView.Model.Service.Events;
using NicoView.Model.Service.Results;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NicoView.Model.Service.Broadcast
{
    public class NicoViewBroadcastController:NicoViewObservableObject
    {



        public NicoViewBroadcastPreset Preset
        {
            get;
            private set;
        }


        private NicoViewApplication baseApplication;

        public event Action<NicoViewBroadcastQueueingEventArgs> Queued;

        

        public NicoViewBroadcastController(NicoViewBroadcastPreset preset,NicoViewApplication baseApplication)
        {
            this.Preset = preset;

            this.Queued = null;

            this.currentCommunityInfo = null;
            this.baseApplication = baseApplication;

            this.broadcastingLiveId = "";

        }



        #region プロパティ

        public NicoLiveBroadcastableCommunityInfo CurrentCommunityInfo
        {
            get
            {

                if (this.currentCommunityInfo == null )
                {
                    setCurrentCommuinityInfo();
                }
                return this.currentCommunityInfo;

            }

            set
            {
                this.Preset.CommunityId = value.CommunityId;
                
                this.Set(() => this.CurrentCommunityInfo, ref this.currentCommunityInfo, value);
                
            }
        }
        private NicoLiveBroadcastableCommunityInfo currentCommunityInfo;


        public IBroadcastMediaEncoder Encoder
        {
            get
            {
                return this.encoder;
            }

            set
            {
                this.Set(() => this.Encoder, ref this.encoder, value);
            }
        }

        private IBroadcastMediaEncoder encoder;


        /// <summary>
        /// 放送中の生放送Id
        /// </summary>
        public string BroadcastingLiveId
        {
            get
            {
                return broadcastingLiveId;;
            }
            set
            {
                Set(()=>this.BroadcastingLiveId, ref broadcastingLiveId, value);
            }
        }
        private string broadcastingLiveId; 

        private bool enableRequest = false;

        /// <summary>
        /// リクエストが有効な状態か判定
        /// </summary>
        public bool EnableRequest
        {
            get
            {
                return enableRequest;
            }
            set
            {
                Set(()=>this.EnableRequest, ref enableRequest, value);
            }
        }

        /// <summary>
        /// 現在放送中か判定
        /// </summary>
        public bool IsBroadcasting
        {
            get
            {
                return this.isBroadcasting;
            }

            set
            {
                this.Set(() => this.IsBroadcasting, ref this.isBroadcasting, value);
            }
        }

        private bool isBroadcasting;

        private void setCurrentCommuinityInfo()
        {
            
                var selectCommunityInfos = from selectCommunityInfo in this.CommunityInfos
                                           where selectCommunityInfo.CommunityId == this.Preset.CommunityId
                                           select selectCommunityInfo;

                if (selectCommunityInfos.Count() > 0)
                {
                    this.CurrentCommunityInfo = selectCommunityInfos.First();
                    
                }
            
        }

        
        /// <summary>
        /// 放送可能なコミュニティ情報
        /// </summary>
        public ObservableCollection<NicoLiveBroadcastableCommunityInfo> CommunityInfos
        {
            get
            {
                lock (communityInfos)
                {
                    if (communityInfos.Count <= 0)
                    {
                        updateBroadcastableInfoAsync();
                    }
                }
                
                return communityInfos;
            }

            
        }
        private static readonly ObservableCollection<NicoLiveBroadcastableCommunityInfo> communityInfos = new ObservableCollection<NicoLiveBroadcastableCommunityInfo>();

        #endregion

        #region メソッド
        internal void OnQueued(NicoViewBroadcastQueueingEventArgs args)
        {
            if (this.Queued != null) this.Queued(args);
        }

        internal NicoLiveBroadcastCreateQueryInfo CreateAsBroadcastCreateQueryInfo()
        {
            return this.Preset.CreateAsBroadcastCreateQueryInfo(this.CurrentCommunityInfo);
        }


        private async void updateBroadcastableInfoAsync()
        {

            var response = await this.baseApplication.Instance.GetBroadcastableInfoAsync();

            if (response.Succeed)
            {
                lock (communityInfos)
                {
                    if (communityInfos.Count <= 0)
                    {
                        foreach (var communityInfo in response.Value.BroadcastableCommunityInfos)
                        {

                            communityInfos.Add(communityInfo);
                        }

                        setCurrentCommuinityInfo();
                    }
                    
                }
                
                
            }
        }

        /// <summary>
        /// 非同期に放送を開始
        /// </summary>
        /// <returns></returns>
        public async Task<NicoViewStartBroadcastResult> StartBroadcastAsync()
        {
            var result = await this.baseApplication.Instance.StartBroadcastAsync(this);
            if (result.Succeed)
            {
                this.baseApplication.Instance.BroadcastingController = this;
            }

            return result;
        }


        /// <summary>
        /// 非同期に放送を停止
        /// </summary>
        /// <returns></returns>
        public async Task<NicoViewStopBroadcastResult> StopBroadcastAsync()
        {
            this.StopEncode();
            var result =  await this.baseApplication.Instance.StopBroadcastAsync(this).ConfigureAwait(false);

            if (result.Succeed)
            {
                this.baseApplication.Instance.BroadcastingController = null;
            }
            return result;
        }


        /// <summary>
        /// エンコードの開始
        /// </summary>
        internal void StartEncode()
        {
            if (this.Encoder != null && this.IsBroadcasting)
            {
                //エンコーダの操作失敗でアプリケーションをさせないため空キャッチ
                try
                {
                    this.Encoder.StartEncode(new BroadcastMediaEncodeStartInfo());
                }
                catch 
                {

                }
                
            }
        }

        /// <summary>
        /// エンコードの停止
        /// </summary>
        internal void StopEncode()
        {
            if (this.Encoder != null && this.IsBroadcasting)
            {
                //エンコーダの操作失敗でアプリケーションをさせないため空キャッチ
                try
                {
                    this.Encoder.StopEncode();
                }
                catch
                {

                }

                
            }
        }

        public object Clone()
        {
            var newController =  (NicoViewBroadcastController)this.MemberwiseClone();
            newController.Preset = (NicoViewBroadcastPreset) this.Preset.Clone();
            return newController;
        }
        #endregion
    }
}
